#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "cJSON.h"

#define SERVICE_PORT 8888             // 命令服务端口（与 Windows 发送端一致）
#define TCPSERVER_IP "192.168.50.164" // tcp服务端ip

int main(int argc, char const *argv[])
{
    // json解析
    FILE *fp;
    char jsonbuf[4096] = "";
    // 读取json文件中的数据
    fp = fopen("./dev.json", "r");
    if (fp == NULL)
    {
        perror("fopen err");
        return -1;
    }
    fread(jsonbuf, 4096, 1, fp);
    // 将json字符串转换为cJSON树结构
    cJSON *root = cJSON_Parse(jsonbuf);
    cJSON *mqtt_server = cJSON_GetObjectItem(root, "mqtt_server");
    cJSON *mqtt_address = cJSON_GetObjectItem(mqtt_server, "addr");
    cJSON *mqtt_port = cJSON_GetObjectItem(mqtt_server, "port");
    cJSON *version = cJSON_GetObjectItem(root, "version");
    //  cJSON *file_name = cJSON_GetObjectItem(root, "file_name");
    //  cJSON *file_len = cJSON_GetObjectItem(root, "file_len");
    cJSON *md5 = cJSON_GetObjectItem(root, "md5");
    printf("%s:%s\n", version->string, version->valuestring);
    // UDP
    char buf[128] = {0};
    int sockfd;
    struct sockaddr_in udp_saddr, udp_caddr, tcp_saddr, tcp_caddr, file_saddr, file_caddr;
    socklen_t len = sizeof(udp_caddr);

    // 1. 创建 UDP 套接字
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        perror("socket creation failed");
        return -1;
    }
    printf("Socket created successfully. sockfd=%d\n", sockfd);

    // 2. 配置本地地址（关键修改：绑定到 INADDR_ANY）
    memset(&udp_saddr, 0, sizeof(udp_saddr));
    udp_saddr.sin_family = AF_INET;
    udp_saddr.sin_port = htons(SERVICE_PORT);
    udp_saddr.sin_addr.s_addr = INADDR_ANY; // 接收所有接口的广播

    // 3. 绑定套接字
    if (bind(sockfd, (struct sockaddr *)&udp_saddr, sizeof(udp_saddr)) < 0)
    {
        perror("bind failed");
        close(sockfd);
        return -1;
    }
    printf("UDP client listening on port %d...\n", SERVICE_PORT);

    // 4. 循环接收广播消息
    while (1)
    {
        memset(buf, 0, sizeof(buf));

        // 接收消息（添加错误检查）
        int recv_len = recvfrom(sockfd, buf, sizeof(buf), 0,
                                (struct sockaddr *)&udp_caddr, &len);
        if (recv_len < 0)
        {
            perror("recvfrom failed");
            continue; // 继续等待下一个消息
        }

        // 打印发送方信息和消息内容
        printf("Received from %s:%d\n",
               inet_ntoa(udp_caddr.sin_addr), ntohs(udp_caddr.sin_port));
        printf("buf:%s\n", buf);
        // 5. 新增：如果收到 "stm32" 消息，回复 "yes"
        if (strncmp(buf, "stm32", 5) == 0)
        {
            printf("stm32\n");
            const char *response = "yes";
            int send_len = sendto(sockfd, response, strlen(response), 0,
                                  (struct sockaddr *)&udp_caddr, len);
            if (send_len < 0)
            {
                perror("sendto failed");
            }
            else
            {
                printf("Response sent to %s:%d\n",
                       inet_ntoa(udp_caddr.sin_addr), ntohs(udp_caddr.sin_port));
            }
            break;
        }
    }
    printf("准备tcp链接\n");
    memset(buf, 0, sizeof(buf));
    // 创建tcp套接字
    int tcpsockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (tcpsockfd < 0)
    {
        perror("sock err");
        return -1;
    }
    printf("sockfd:%d\n", tcpsockfd);
    // 2.指定服务器网络信息
    tcp_saddr.sin_family = AF_INET;
    tcp_saddr.sin_port = htons(8889);
    tcp_saddr.sin_addr.s_addr = INADDR_ANY;
    len = sizeof(tcp_caddr);
    // 3.绑定套接字（bind）
    if (bind(tcpsockfd, (struct sockaddr *)&tcp_saddr, sizeof(tcp_saddr)) < 0)
    {
        perror("bind err");
        return -1;
    }
    printf("bind okk\n");
    // 4.监听（listen）:将主动套接字变为被动套接字
    if (listen(tcpsockfd, 6) < 0)
    // 队列1:(未连接队列)  4 5 6
    // 队列2:(已连接队列) 3
    {
        perror("listen err");
        return -1;
    }
    printf("listen okk\n");
    int acceptfd;
    int ret;
    while (1)
    {
        // 5.接收客户端连接请求（accept）
        // 阻塞等待客户端连接
        acceptfd = accept(tcpsockfd, (struct sockaddr *)&tcp_caddr, &len);
        if (acceptfd < 0)
        {
            perror("accept err");
            return -1;
        }
        printf("acceptfd:%d\n", acceptfd);
        printf("ip:%s port:%d\n", inet_ntoa(tcp_caddr.sin_addr), ntohs(tcp_caddr.sin_port));
        memset(buf, 0, sizeof(buf));
        cJSON *attrackroot = cJSON_CreateObject();
        // 在根节点上添加子节点
        cJSON_AddItemToObject(attrackroot, "type", cJSON_CreateNumber(0));
        cJSON_AddItemToObject(attrackroot, "attrack", cJSON_CreateString("ok"));
        char *attrackdStr = cJSON_Print(attrackroot);
        cJSON_Delete(attrackroot);
        // 向qt发送已经准备好了
        if (send(acceptfd, attrackdStr, strlen(attrackdStr), 0) < 0)
        {
            perror("send err");
            return -1;
        }
        while (1)
        {
            // 接受qt指令
            recv(acceptfd, buf, sizeof(buf), 0);
            printf("recv:%s\n", buf);
            cJSON *recroot = cJSON_Parse(buf);
            cJSON *type = cJSON_GetObjectItem(recroot, "type");
            if (type->valueint == 0)
            {
                // 获取命令内容
                cJSON *recitem = cJSON_GetObjectItem(recroot, "request");
                printf("recitem:%s\n", recitem->valuestring);
                // 设备搜索
                if (strcmp(recitem->valuestring, "connect_info") == 0)
                {

                    memset(buf, 0, sizeof(buf));

                    cJSON *sendroot = cJSON_CreateObject();
                    // 发送设备信息

                    cJSON_AddItemToObject(sendroot, "type", cJSON_CreateNumber(0));
                    cJSON *dataroot = cJSON_CreateObject();

                    cJSON_AddItemToObject(sendroot, "mqtt_address", cJSON_CreateString(mqtt_address->valuestring));
                    cJSON_AddItemToObject(sendroot, "mqtt_port", cJSON_CreateNumber(mqtt_port->valueint));

                    char *sendStr = cJSON_Print(sendroot);
                    printf("sendStr:%s\n", sendStr);
                    cJSON_Delete(sendroot);

                    if (send(acceptfd, sendStr, strlen(sendStr), 0) < 0)
                    {
                        perror("send err");
                        return -1;
                    }
                }
                cJSON_Delete(recroot);
            }
            // 设备升级
            else if (type->valueint == 1)
            {
                cJSON *recitem = cJSON_GetObjectItem(recroot, "data");
                cJSON *rever = cJSON_GetObjectItem(recitem, "version");
                cJSON *refile_name = cJSON_GetObjectItem(recitem, "file_name");
                cJSON *refile_len = cJSON_GetObjectItem(recitem, "file_len");
                cJSON *remd5 = cJSON_GetObjectItem(recitem, "md5");
                printf("rever:%s\n", rever->valuestring);
                printf("remd5:%s\n", remd5->valuestring);

                cJSON *sendroot = cJSON_CreateObject();
                // 在根节点上添加子节点

                cJSON_AddItemToObject(sendroot, "type", cJSON_CreateNumber(1));
                cJSON *dataroot = cJSON_CreateObject();
                cJSON_AddItemToObject(sendroot, "data", dataroot);

                if (strcmp(rever->valuestring, version->valuestring) == 0 && strcmp(remd5->valuestring, md5->valuestring) == 0)
                {
                    cJSON_AddItemToObject(dataroot, "updata", cJSON_CreateString("false"));
                    char *sendStr = cJSON_Print(sendroot);
                    cJSON_Delete(sendroot);
                    if (send(acceptfd, sendStr, strlen(sendStr), 0) < 0)
                    {
                        perror("send err");
                        return -1;
                    }
                }
                else
                {
                    cJSON_AddItemToObject(dataroot, "updata", cJSON_CreateString("true"));
                    char *sendStr = cJSON_Print(sendroot);
                    cJSON_Delete(sendroot);
                    if (send(acceptfd, sendStr, strlen(sendStr), 0) < 0)
                    {
                        perror("send err");
                        return -1;
                    }
                    // 创建文件套接字,准备文件传输
                    int filesockfd = socket(AF_INET, SOCK_STREAM, 0);
                    if (filesockfd < 0)
                    {
                        perror("sock err");
                        return -1;
                    }
                    printf("sockfd:%d\n", filesockfd);
                    // 2.指定服务器网络信息
                    file_saddr.sin_family = AF_INET;
                    file_saddr.sin_port = htons(8810);
                    file_saddr.sin_addr.s_addr = INADDR_ANY;
                    len = sizeof(file_caddr);
                    // 3.绑定套接字（bind）
                    if (bind(filesockfd, (struct sockaddr *)&file_saddr, sizeof(file_saddr)) < 0)
                    {
                        perror("bind err");
                        return -1;
                    }
                    printf("bind okk\n");
                    // 4.监听（listen）:将主动套接字变为被动套接字
                    listen(filesockfd, 6);
                    int flieacceptfd = accept(filesockfd, (struct sockaddr *)&tcp_caddr, &len);
                    if (flieacceptfd < 0)
                    {
                        perror("accept err");
                        return -1;
                    }
                    // 5. 接收文件
                    FILE *file = fopen("./1.zip", "wb");
                    if (!file)
                    {
                        perror("fopen failed");
                        close(flieacceptfd);
                        close(filesockfd);
                        exit(EXIT_FAILURE);
                    }

                    // 先接收文件总大小（假设客户端先发送 8 字节的文件大小）
                    long long total_size = 0;
                    if (recv(flieacceptfd, &total_size, sizeof(total_size), 0) <= 0)
                    {
                        perror("recv total_size failed");
                        fclose(file);
                        close(flieacceptfd);
                        close(filesockfd);
                        exit(EXIT_FAILURE);
                    }
                    // 转换字节序（若客户端用 Qt 的 qToBigEndian，需转换）
                    total_size = be64toh(total_size);
                    printf("文件总大小：%lld 字节\n", total_size); // 现在会显示真实大小（如 431）

                    // 循环接收文件内容
                    long long received = 0;
                    ssize_t bytes_read;
                    char filebuffer[1024] = {0};
                    while (received < total_size)
                    {
                        bytes_read = recv(flieacceptfd, filebuffer, sizeof(filebuffer), 0);
                        if (bytes_read <= 0)
                        {
                            perror("recv failed");
                            break;
                        }
                        fwrite(filebuffer, 1, bytes_read, file);
                        received += bytes_read;

                        // 计算进度（可选，打印百分比）
                        int progress = (received * 100) / total_size;
                        printf("\r接收进度：%d%%", progress);
                        fflush(stdout);
                    }
                     // 6. 关闭资源
                    fclose(file);
                    close(flieacceptfd);
                    close(filesockfd);
                    //发送传输完成
                    cJSON *upsendroot = cJSON_CreateObject();
                    cJSON_AddItemToObject(upsendroot, "type", cJSON_CreateNumber(2));
                    cJSON *updataroot = cJSON_CreateObject();
                    cJSON_AddItemToObject(upsendroot, "data", updataroot);
                    cJSON_AddItemToObject(updataroot, "trans_success", cJSON_CreateString("true"));
                    char *updatasendStr = cJSON_Print(upsendroot);
                    cJSON_Delete(upsendroot);
                    if (send(acceptfd, updatasendStr, strlen(updatasendStr), 0) < 0)
                    {
                        perror("send err");
                        return -1;
                    }
                    sleep(1);
                    //解压文件
                    int status = system("unzip -o 1.zip");

                    if (status == -1)
                    {
                        perror("system()调用失败");
                        return 1;
                    }
                    else if (WIFEXITED(status))
                    {
                        printf("解压完成，退出状态：%d\n", WEXITSTATUS(status));
                    }
                    else
                    {
                        printf("解压异常终止\n");
                    }
                     status = system("rm -r 1.zip");

                    if (status == -1)
                    {
                        perror("system()调用失败");
                        return 1;
                    }
                    else if (WIFEXITED(status))
                    {
                        printf("解压完成，退出状态：%d\n", WEXITSTATUS(status));
                    }
                    else
                    {
                        printf("解压异常终止\n");
                    }
                   sleep(1);
                    cJSON *fupsendroot = cJSON_CreateObject();
                    cJSON_AddItemToObject(fupsendroot, "type", cJSON_CreateNumber(3));
                    cJSON *fupdataroot = cJSON_CreateObject();
                    cJSON_AddItemToObject(fupsendroot, "data", fupdataroot);
                    cJSON_AddItemToObject(fupdataroot, "updata_success", cJSON_CreateString("true"));
                    char *fupdatasendStr = cJSON_Print(fupsendroot);
                    cJSON_Delete(fupsendroot);
                    if (send(acceptfd, fupdatasendStr, strlen(fupdatasendStr), 0) < 0)
                    {
                        perror("send err");
                        return -1;
                    }
                }
            }
            memset(buf, 0, sizeof(buf));
        }
        break;

    }
    close(acceptfd);
    close(tcpsockfd);
    close(sockfd);
    // 6. 关闭套接字（不会执行到这里，按 Ctrl+C 终止程序）

    return 0;
}